package com.geese.module.wechat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.geese.common.constants.BusinessConstants;
import com.geese.common.constants.Constants;
import com.geese.common.entity.*;
import com.geese.common.util.BeanUtil;
import com.geese.common.util.DateUtil;
import com.geese.common.util.MD5Util;
import com.geese.common.util.PageUtil;
import com.geese.common.vo.Page;
import com.geese.common.vo.Paginator;
import com.geese.exception.BusinessException;
import com.geese.module.business.dao.BusinessMapper;
import com.geese.module.ceo.dao.CashMapper;
import com.geese.module.ceo.dao.CourierMapper;
import com.geese.module.ceo.dao.OrderMapper;
import com.geese.module.ceo.dao.SchoolMapper;
import com.geese.module.ceo.model.CourierModel;
import com.geese.module.user.dao.AccountMapper;
import com.geese.module.user.dao.UserMapper;
import com.geese.module.user.model.SecurityUser;
import com.geese.module.wechat.dao.WithdrawAccountMapper;
import com.geese.module.wechat.dto.WaiterCashDTO;
import com.geese.module.wechat.dto.WithdrawAccountDTO;
import com.geese.module.wechat.service.IWaiterService;
import com.geese.module.wechat.vo.CourierOrderVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import ma.glasnost.orika.metadata.Type;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.method.P;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by huweiwei on 2017/3/9.
 */
@Service
public class WaiterServiceImpl implements IWaiterService {

    private final static Logger logger = Logger.getLogger(WaiterServiceImpl.class);

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private CourierMapper courierMapper;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CashMapper cashMapper;
    @Autowired
    private SchoolMapper schoolMapper;
    @Autowired
    private BusinessMapper businessMapper;
    @Autowired
    private WithdrawAccountMapper withdrawAccountMapper;

    /**
     * 注册
     * @param courier
     * @param password
     */
    @Override
    public void doRegister(Courier courier, String password) {
        //账号唯一性校验
        String account = courier.getMobile();
        Account accountDO = accountMapper.findByAccount(account);
        if (null != accountDO) {
            throw new BusinessException(120076);
        }

        //新增用户信息
        User user = new User();
        user.setUsername(courier.getName());
        user.setMobile(account);
        user.setUserType(BusinessConstants.WAITER_TYPE);
        user.setBlock(0);
        user.setEnable(1);
        userMapper.save(user);
        Integer userId = user.getId();
        if (null == userId || userId <= 0) {
            throw new BusinessException(120075);
        }

        //获取用户id,新增账号信息
        accountDO = new Account();
        accountDO.setAccount(account);
        accountDO.setEnable(1);
        accountDO.setBlock(0);
        accountDO.setUserId(userId);
        accountDO.setPassword(MD5Util.encrypt(password));
        accountDO.setAllowPoint(0);
        accountMapper.save(accountDO);
        Integer accountId = accountDO.getId();
        if (null == accountId || accountId <= 0) {
            throw new BusinessException(120074);
        }

        //获取用户id,新增小二信息
        // TODO: 2017/3/10 小二工号生成规则
        String code = "";
        courier.setCode(code);
        courier.setUserId(userId);
        courier.setAmount(0d);
        courier.setCeo(BusinessConstants.WAITER);
        courier.setAudit(0);
        courier.setBlock(0);
        courier.setEnable(1);
        courierMapper.save(courier);
        Integer courierId = courier.getId();
        if (null == courierId || courierId <= 0) {
            throw new BusinessException(120096);
        }
    }

    /**
     * 展示接单详情
     * @param orderId
     * @return
     */
    @Override
    public Map<String, Object> showOrder(int orderId) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (null == order) {
            throw new BusinessException(120070);
        }
        //orderStatus == 0  已下单状态
//        if (order.getStatus() != 0) {
//            throw new RuntimeException("订单已被人抢先一步了");
//        }
        Map<String, Object> result = new HashMap<>();
        result.put("orderSendTime", order.getSendTime());
        result.put("orderId", order.getId());
        result.put("orderCode", order.getCode());
        result.put("orderBusinessName", order.getBusinessName());
        result.put("orderImg", order.getImageUrl());
        return result;
    }

    @Override
    public Map<String, Object> orderShow(int orderCode) {
        Order order = orderMapper.selectByOrderCode(orderCode);
        if (null == order) {
            throw new BusinessException(120070);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("orderSendTime", order.getSendTime());
        result.put("orderId", order.getId());
        result.put("orderCode", order.getCode());
        result.put("orderBusinessName", order.getBusinessName());
        result.put("orderImg", order.getImageUrl());
        return result;
    }

    /**
     * 订单详情
     * @param orderId
     * @return
     */
    @Override
    public Map<String, Object> orderDetails(int orderId) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (null == order) {
            throw new BusinessException(120070);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("orderCourierMobile",  order.getStatus() > 0 ? courierMapper.findById(order.getCourierId()).getMobile() : "");
        result.put("orderId", order.getId());
        result.put("orderSendTime", order.getSendTime());
        result.put("orderReceiveTime", order.getReceiveTime());
        result.put("orderBusinessName", order.getBusinessName());
        result.put("orderCourierName", order.getCourierName());
        result.put("orderImg", order.getImageUrl());
        result.put("orderCode", order.getCode());
        result.put("orderStatus", order.getStatus());
        return result;
    }

    /**
     * 接单
     * @param orderId
     */
    @Override
    public void doOrders(int orderId, SecurityUser user) {
        Courier courier = courierMapper.findByUserId(user.getUserId());
        if (null == courier) {
            throw new BusinessException(120092);
        }
        if (courier.getBlock() == 1) {
            throw new BusinessException(120093);
        }
        if (courier.getAudit() != 1) {
            throw new BusinessException(120094);
        }
        if (courier.getCeo() == 1) {
            throw new BusinessException(120095);
        }

        //1.验证订单状态
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (null == order) {
            throw new BusinessException(120070);
        }
        //orderStatus == 0  已下单状态
        if (order.getStatus() > 0) {
            throw new BusinessException(120091);
        }
        //2.修改订单状态, status == 1 已接单
        order.setStatus(BusinessConstants.ORDER_STATUS_RECEIVE);
        order.setCourierId(courier.getId());
        order.setCourierName(courier.getName());
        order.setReceiveTime(new Date());
        order.setSchoolId(courier.getSchoolId());
        int skip = orderMapper.updateByPrimaryKeySelective(order);
        if (skip != 1) {
            throw new BusinessException(120090);
        }
    }

    /**
     * 个人中心
     * @return
     */
    @Override
    public Map<String, Object> courierInfo(SecurityUser user) {
        CourierModel courierModel = courierMapper.findInfoByUserId(user.getUserId());
        if (null == courierModel) {
            throw new BusinessException(120045);
        }
        School school = schoolMapper.findById(courierModel.getSchoolId());
        Map<String, Object> result = new HashMap<>();
        result.put("courierId", courierModel.getId());
        //头像没字段
//        result.put("courier", courier.get);
        result.put("courierName", courierModel.getName());
        result.put("courierAmount", courierModel.getAmount());
        result.put("courierMobile", courierModel.getMobile());
        result.put("courierStudentCard", courierModel.getStudentCard());
        if (courierModel.getAmount() < school.getCardinalNumber()) {
            result.put("cardinalAmount", 0);
        } else {
            result.put("cardinalAmount", school.getCardinalNumber());
        }
        //楼幢信息
        StringBuilder sb = new StringBuilder();
        sb.append(courierModel.getSchoolName())
          .append(courierModel.getCampusName())
          .append(courierModel.getBuildingName());
        result.put("courierBuilding", sb.toString());
        return result;
    }

    /**
     * 查询小二提现账户余额信息
     * @param user
     * @return
     */
    @Override
    public Map<String, Object> amount(SecurityUser user) {
        CourierModel courierModel = courierMapper.findInfoByUserId(user.getUserId());
        if (null == courierModel) {
            throw new BusinessException(120045);
        }
        School school = schoolMapper.findById(courierModel.getSchoolId());
        Map<String, Object> result = new HashMap<>();
        result.put("id", courierModel.getId());
        result.put("amount", courierModel.getAmount());
        result.put("cardinalNumber", school.getCardinalNumber());
        return result;
    }

    /**
     * 订单列表
     * @param courierOrderVO
     * @return
     */
    @Override
    public Map<String, Object> orderList(CourierOrderVO courierOrderVO, SecurityUser user) {
        Courier courier = courierMapper.findByUserId(user.getUserId());
        if (null == courier) {
            throw new BusinessException(120077);
        }
        courierOrderVO.setCourierId(courier.getId());

        Map<String, Object> result = new HashMap<>();
        PageHelper.startPage(courierOrderVO.getCurrPage(), courierOrderVO.getPageSize(), " id DESC");
        List<Order> orderList = orderMapper.selectOrderForCourier(courierOrderVO);

        Map<String, Object> pageInfo = new HashMap<>();
        if (CollectionUtils.isEmpty(orderList)) {
            pageInfo.put("currPage", 1);
            pageInfo.put("totalPage", 1);
            pageInfo.put("total", 0);
            result.put("pageInfo", pageInfo);
            result.put("orderList", orderList);
            return result;
        }

        PageInfo listInfo = new PageInfo(orderList);
        pageInfo.put("currPage", listInfo.getPageNum());
        pageInfo.put("totalPage", listInfo.getPages());
        pageInfo.put("total", listInfo.getTotal());

        List<Map<String, Object>> orders = new ArrayList<>(orderList.size());
        for (Order order : orderList) {
            Map<String, Object> map = new HashMap<>(orderList.size());
            map.put("orderId", order.getId());
//            map.put("orderSendTime", DateUtil.format(order.getSendTime()));
//            map.put("orderReceiveTime", DateUtil.format(order.getReceiveTime()));
            map.put("orderSendTime", order.getSendTime());
            map.put("orderReceiveTime", order.getReceiveTime());
            map.put("orderBusinessName", order.getBusinessName());
            map.put("orderCourierName", order.getCourierName());
            map.put("orderImg", order.getImageUrl());
            map.put("orderCode", order.getCode());
            map.put("orderStatus", order.getStatus());
            orders.add(map);
        }
        result.put("pageInfo", pageInfo);
        result.put("orderList", orders);
        return result;
    }

    @Override
    public void doCash(SecurityUser user, int id) {
        Courier courier = courierMapper.findByUserId(user.getUserId());
        if (courier == null) {
            throw new BusinessException(120078);
        }
        if (courier.getBlock() == 1) {
            throw new BusinessException(120079);
        }
        School school = schoolMapper.findById(courier.getSchoolId());
        if (school == null) {
            throw new BusinessException(120081);
        }
        if (courier.getAmount() < school.getCardinalNumber()) {
            throw new BusinessException(120082);
        }
        WithdrawAccount withdrawAccount = withdrawAccountMapper.findById(id);
        if (withdrawAccount == null) {
            throw new BusinessException(120125);
        }
        courier.setAmount(courier.getAmount() - school.getCardinalNumber());
        courierMapper.update(courier);

        Cash cash = new Cash();
        cash.setAmount(school.getCardinalNumber());
        cash.setApplyTime(new Date());
        cash.setCourierId(courier.getId());
        cash.setCourierMobile(courier.getMobile());
        cash.setCourierName(courier.getName());
        cash.setStatus(BusinessConstants.CASH_STATUS_APPLY);
        cash.setEnable(1);
        cash.setAccount(withdrawAccount.getAccount());
        Integer oid = RandomUtils.nextInt(1000000000, Integer.MAX_VALUE);//10位随机数字
        cash.setOid(oid);
        cashMapper.insertCash(cash);
        if (cash.getId() == null || cash.getId() <= 0) {
            throw new BusinessException(120083);
        }
    }

    @Override
    public void doComplete(SecurityUser user, int orderId) {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order == null) {
            throw new BusinessException(120084);
        }
        if (order.getStatus() != 1) {
            throw new BusinessException(120085);
        }
        Courier courier = JSONObject.parseObject(user.getExtra(), Courier.class);
        if (courier == null) {
            throw new BusinessException(120086);
        }
        if (!Objects.equals(courier.getId(), order.getCourierId())) {
            throw new BusinessException(120087);
        }
        Date receiveTime = order.getReceiveTime();
        Date check = DateUtil.addMinutes(receiveTime, 5);
        if (check.getTime() > System.currentTimeMillis()) {
            throw new BusinessException(120089);
        }
        courier.setAmount(courier.getAmount() + order.getOrderAmount());
        courierMapper.update(courier);
        order.setStatus(BusinessConstants.ORDER_STATUS_COMPLETE);
        order.setCompleteTime(new Date());
        orderMapper.updateByPrimaryKeySelective(order);
    }

    @Override
    public void addAccount(WithdrawAccount withdrawAccount) {
        withdrawAccountMapper.insertAccount(withdrawAccount);
        if (withdrawAccount.getId() == null) {
            throw new BusinessException(120033);
        }
    }

    @Override
    public void editAccount(WithdrawAccount withdrawAccount) {
        WithdrawAccount check = withdrawAccountMapper.findById(withdrawAccount.getId());
        if (!Objects.equals(check.getUserId(), withdrawAccount.getUserId())) {
            throw new BusinessException(120126);
        }
        int skip = withdrawAccountMapper.updateAccount(withdrawAccount);
        if (skip != 1) {
            throw new BusinessException(120033);
        }
    }

    @Override
    public void deleteAccount(int id) {
        int skip = withdrawAccountMapper.deleteAccount(id);
        if (skip != 1) {
            throw new BusinessException(120033);
        }
    }

    @Override
    public List<WithdrawAccountDTO> listAccount(Integer userId) {
        List<WithdrawAccount> withdrawAccounts = withdrawAccountMapper.findByUserId(userId);
        Type<WithdrawAccount> source = BeanUtil.getType(WithdrawAccount.class);
        Type<WithdrawAccountDTO> target = BeanUtil.getType(WithdrawAccountDTO.class);
        return BeanUtil.mapList(withdrawAccounts, source, target);
    }

    @Override
    public Map<String, Object> getCashList(SecurityUser user, Page page) {
        String json = user.getExtra();
        Courier courier = JSON.parseObject(json, Courier.class);
        if (courier == null) {
            throw new BusinessException(120077);
        }
        PageHelper.startPage(page.getCurrPage(), page.getPageSize());
        List<Cash> cashes = cashMapper.findByCourierId(courier.getId());
        Type<Cash> source = BeanUtil.getType(Cash.class);
        Type<WaiterCashDTO> target = BeanUtil.getType(WaiterCashDTO.class);
        List<WaiterCashDTO> cashDTOs = BeanUtil.mapList(cashes, source, target);

        Map<String, Object> result = Maps.newHashMap();
        Paginator<Cash> pages = PageUtil.getPage(cashes);
        result.put(Constants.PAGE_INFO, pages.getPageResult());
        result.put("cashList", cashDTOs);
        return result;
    }
}
